﻿#region License Information (GPL v2)
/*
    Source Queries - Source Server Queries
    Copyright (C) 2009  Source Queries Developers

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    
    Optionally you can also view the license at <http://www.gnu.org/licenses/>.
*/
#endregion

using System;
using System.IO;
using System.Text;

namespace SourceQueries
{
    public class RCONPacket
    {
        public int RequestID = 0;
        public ServerDataSend Command;
        public ServerDataReceive Response;
        public string String1 = string.Empty, String2 = string.Empty;

        public enum ServerDataSend
        {
            SERVERDATA_AUTH = 3,
            SERVERDATA_EXECCOMMAND = 2
        }

        public enum ServerDataReceive
        {
            SERVERDATA_RESPONSE_VALUE = 0,
            SERVERDATA_AUTH_RESPONSE = 2
        }

        public byte[] GetBytes()
        {
            byte[] packetSize, requestID, serverData, string1, string2, result;

            requestID = BitConverter.GetBytes(RequestID);
            serverData = BitConverter.GetBytes((int)Command);
            string1 = Encoding.ASCII.GetBytes(String1);
            string2 = Encoding.ASCII.GetBytes(String2);

            // 4 (Packet Size) + 4 (Request ID) + 4 (Server Data) + <String1 Length> + 1 (null) + <String2 Length> + 1 (null)
            result = new byte[14 + string1.Length + string2.Length];

            // <Result Length> - 4 (Packet Size)
            packetSize = BitConverter.GetBytes(result.Length - 4);

            MemoryStream memory = new MemoryStream(result);
            memory.Write(packetSize, 0, packetSize.Length);
            memory.Write(requestID, 0, requestID.Length);
            memory.Write(serverData, 0, serverData.Length);
            memory.Write(string1, 0, string1.Length);
            memory.WriteByte(0x00);
            memory.Write(string2, 0, string2.Length);
            memory.WriteByte(0x00);

            return result;
        }

        public static RCONPacket Parse(byte[] bytes)
        {
            RCONPacket packet = new RCONPacket();
            int offset = 0;

            packet.RequestID = bytes.ToInt32(offset);
            offset += 4;
            packet.Response = (ServerDataReceive)bytes.ToInt32(offset);
            offset += 4;
            packet.String1 = bytes.ToStringUntilNull(offset);
            offset += packet.String1.Length + 1;
            packet.String2 = bytes.ToStringUntilNull(offset);
            offset += packet.String2.Length + 1;

            if (bytes.Length != offset)
            {
#if DEBUG
                Console.WriteLine("Error parse: Bytes length: {0}, Offset: {1}", bytes.Length, offset);
#endif
            }

            return packet;
        }
    }
}